#ifndef BOARD_H
#define BOARD_H

#include <esp_err.h>
#include <array>
#include <atomic>

#include <driver/gpio.h>
#include <driver/i2c_types.h>

#include <memory> // For std::unique_ptr

#include "ws2812.h"
#include "PCF8574.h"
#include "HTTPClient.h"
#include "esp_i2c_master.h"
#include "HttpsOTA.h"

class Board {
public:
    static Board& GetInstance() {
        static Board instance;
        return instance;
    }

    // 删除拷贝构造函数和赋值运算符
    Board(const Board&) = delete;
    Board& operator=(const Board&) = delete;
    
    virtual esp_err_t Start();
    virtual esp_err_t StartNetwork();
    virtual void StartOta();

    WS2812* GetWS2812();

    /**
     * @brief 获取所有PCF8574实例的指针数组
     * @return std::array<PCF8574*, 3> 包含3个PCF8574指针的数组
     * @note 数组索引: [0]=pcf8574_1_(0x21), [1]=pcf8574_2_(0x20), [2]=pcf8574_3_(0x22)
     * @warning 返回的指针仅在Board对象生命周期内有效
     */
    std::array<PCF8574*, 3> GetPCF8574Array();
    
    /**
     * @brief 根据索引获取指定的PCF8574实例
     * @param index PCF8574索引 (0-2)
     * @return PCF8574* 指向指定PCF8574实例的指针，无效索引返回nullptr
     */
    PCF8574* GetPCF8574(size_t index);
    
    /**
     * @brief 读取5位拨码开关的数值
     * @return uint8_t 拨码开关的数值(0-31)，每一位对应一个开关位置
     * @note 返回值为5位二进制数，如：开关状态为01101，则返回13
     */
    uint8_t ReadDipSwitch();

private:
    Board();
    ~Board();
    
    HTTPClient http_client;

    
    // OTA并发控制 - 仅使用原子变量，无需互斥锁
    std::atomic<bool> ota_in_progress_{false};  // OTA执行中标志
    std::atomic<bool> ota_completed_{false};    // OTA完成标志

    // I2C主控实例
    std::shared_ptr<I2cMaster> i2c_;

    // WS2812实例
    std::unique_ptr<WS2812> ws2812_;

    // PCF8574实例 - 使用unique_ptr表示唯一所有权
    std::unique_ptr<PCF8574> pcf8574_1_;
    std::unique_ptr<PCF8574> pcf8574_2_;
    std::unique_ptr<PCF8574> pcf8574_3_;

    // 5位拨码开关GPIO引脚定义
    static constexpr gpio_num_t DIP_SWITCH_PINS[5] = {
        GPIO_NUM_13,   // 第1位
        GPIO_NUM_16,   // 第2位  
        GPIO_NUM_17,   // 第3位
        GPIO_NUM_18,   // 第4位
        GPIO_NUM_19    // 第5位
    };

    void WifiConfig();    // WiFi配置

    esp_err_t InitializeI2C(i2c_port_num_t port, gpio_num_t scl, gpio_num_t sda);    // 初始化I2C
    esp_err_t InitializePCF8574();    // 初始化PCF8574
    esp_err_t InitializeWS2812(int gpio_pin, int led_count);    // 初始化WS2812
    esp_err_t InitializeDipSwitch();    // 初始化拨码开关GPIO

};

#endif // BOARD_H